package com.zhj.rabbitmq.com.service;

import com.zhj.rabbitmq.com.common.RabbitmqUtils;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @program: rabbimmq-demo
 * @description:
 * @author: zhengjibin
 * @create: 2020-11-19 13:46
 * @Version 1.0
 **/
@Service
public class RabbitmqServiceImpl implements RabbitmqService {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送消息
     * @param message 消息内容
     */
    @Override
    public void sendDirectMessage(String message) {
        //rabbitTemplate.send();//这种方式需要创建一个Message对象

        System.out.println("发送消息");
         /*
            发送消息
            参数1：exchange
            参数2：routingkey
            参数3：消息内容
         */
        rabbitTemplate.convertAndSend(RabbitmqUtils.directExchangeName,RabbitmqUtils.directBootRoutingkey,message);//转换数据，并发送

        System.out.println("消息发送完成");
    }

    /**
     * 手动 接收消息
     * @return 返回消息内容
     */
    @Override
    public String directReceiveMessage() {
        //获取队列消息
        //还有方法receive ，返回的是message对象。
        //receiveAndConvert 方法直接返回的消息内容
        String message = (String) rabbitTemplate.receiveAndConvert(RabbitmqUtils.directQueueName);
        System.out.println("手动获得消息："+message);
        return message;
    }

    /**
     * 自动接收消息
     * RabbitListener 注解标记当前方法是一个rabbitmq的监听器。持续的读取队列中的消息内容
     *                  此注解中，指定队列名称，bindingkey的绑定，是否自动确认等功能
     *             注意使用了此注解：方法不能有返回值
     * @return 返回消息内容
     */
    @RabbitListener(queues = {RabbitmqUtils.directQueueName})
    @Override
    public void directReceiveMessageListener(String message) {
        System.out.println("direct 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
            //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }
    ///////////////////////////////////////////////////////////fanout 类型交换机
    /**
     * 由于fanout是广播模式，不需要指定队列，所以使用方法比较复杂
     * RabbitListener 注解参数说明
     *  参数bindings：指定binding绑定信息，由于参数类型是一个注解，所以写法是@QueueBinding()
     *  参数@QueueBinding：由于value和exchange是没有默认值的所以必须要指定。
     *      value参数对象是一个@Queue的注解，由于这个注解的参数都有默认值，所以不用指定值。而且fanout类型交换机队列名称没法写死，所以就用默认的
     *      exchange参数对象是一个@Exchange的注解，虽然都有默认值，但是我们也要知道交换机名称和交换机类型
     *      注解类型的参数写的方式都是@Exchange()
     *
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(),exchange = @Exchange(name=(RabbitmqUtils.fanoutExchangeName),type=RabbitmqUtils.fanoutType))})
    @Override
    public void fanoutReceiveMessageListener01(String message) {
        System.out.println("fanout011111 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }

    /**
     * 注解实现：不用 实现接口也行
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(),exchange = @Exchange(name=(RabbitmqUtils.fanoutExchangeName),type=RabbitmqUtils.fanoutType))})
    public void fanoutReceiveMessageListener02(String message) {
        System.out.println("fanout02222 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }

    /**
     * fanout类型交换机消息发送
     * @param message
     */
    @Override
    public void sendFanoutMessage(String message) {
        rabbitTemplate.convertAndSend(RabbitmqUtils.fanoutExchangeName,"",message);
    }

    /////////////////////////////////////////////////////////topic 类型交换机
    /**
     * 注解实现: topic 类型交换机消息接收 。与fanout方式差不多
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(value = RabbitmqUtils.topic01QueueName),
                                            key = RabbitmqUtils.topic01BootRoutingkey,//key是属于QueueBinding的绑定属性
                                            exchange = @Exchange(name=(RabbitmqUtils.topicExchangeName),type=RabbitmqUtils.topicType)
                                            )
                            }
                    )
    public void topicReceiveMessageListener01(String message) {
        System.out.println("topic01：routingkey=aa 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }

    /**
     * 注解实现: topic 类型交换机消息接收 。与fanout方式差不多
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(value = RabbitmqUtils.topic02QueueName),
            key = RabbitmqUtils.topic02BootRoutingkey,//key是属于QueueBinding的绑定属性
            exchange = @Exchange(name=(RabbitmqUtils.topicExchangeName),type=RabbitmqUtils.topicType)
    )
    }
    )
    public void topicReceiveMessageListener02(String message) {
        System.out.println("topic02：routingkey=aa.* 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }

    /**
     * 注解实现: topic 类型交换机消息接收 。与fanout方式差不多
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(value = RabbitmqUtils.topic03QueueName),
            key = RabbitmqUtils.topic03BootRoutingkey,//key是属于QueueBinding的绑定属性
            exchange = @Exchange(name=(RabbitmqUtils.topicExchangeName),type=RabbitmqUtils.topicType)
    )
    }
    )
    public void topicReceiveMessageListener03(String message) {
        System.out.println("topic03：routingkey=aa.bb 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }

    /**
     * 注解实现: topic 类型交换机消息接收 。与fanout方式差不多
     * @param message
     */
    @RabbitListener(bindings={@QueueBinding(value = @Queue(value = RabbitmqUtils.topic04QueueName),
            key = RabbitmqUtils.topic04BootRoutingkey,//key是属于QueueBinding的绑定属性
            exchange = @Exchange(name=(RabbitmqUtils.topicExchangeName),type=RabbitmqUtils.topicType)
    )
    }
    )
    public void topicReceiveMessageListener04(String message) {
        System.out.println("topic04：routingkey=aa.# 自动获得消息："+message);
        //抛出异常。如果没有异常spring会自动确认消息，否则不会确认消息。
        //但是消息是接收了的。而且队列中的消息还存在。这个时候就需要做好消息的重复接收问题
        //System.out.println(10/0);
    }


    @Override
    public void sendTopicMessage(String message, String routingkey) {
        rabbitTemplate.convertAndSend(RabbitmqUtils.topicExchangeName,routingkey,message);
    }
}
